package com.example.instance;

import com.example.channel.BootNettyClientChannel;
import com.example.channel.BootNettyClientChannelCache;
import com.example.config.BootNettyChannelInitializer;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * @ClassName: BootNettyClient
 * @Author : 13736
 * @Date :2023/7/8  15:23
 * @Description: TODO
 * @Version :1.0
 */
@Slf4j
@Component
public class BootNettyClient {

    @Value("${socket.server.port:44000}")
    private int port;

    @Value("${socket.server.host:127.0.0.1}")
    private String host;

    @Autowired
    private BootNettyChannelInitializer bootNettyChannelInitializer;


    public void connect() throws Exception{

        /**
         * 客户端的NIO线程组
         *
         */
        EventLoopGroup group = new NioEventLoopGroup();

        try {
            /**
             * Bootstrap 是一个启动NIO服务的辅助启动类 客户端的
             */
            Bootstrap bootstrap = new Bootstrap();
            bootstrap = bootstrap.group(group);
            bootstrap = bootstrap.channel(NioSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY, true)// 禁用nagle算法
                    .option(ChannelOption.SO_KEEPALIVE, Boolean.TRUE);//保持长连接
            /**
             * 设置 I/O处理类,主要用于网络I/O事件，记录日志，编码、解码消息
             */
            bootstrap = bootstrap.handler(bootNettyChannelInitializer);
            /**
             * 连接服务端
             */
            ChannelFuture future = bootstrap.connect(host, port).sync();
            if(future.isSuccess()) {
                Channel channel = future.channel();
                String id = future.channel().id().toString();
                BootNettyClientChannel bootNettyClientChannel = new BootNettyClientChannel();
                bootNettyClientChannel.setChannel(channel);
                bootNettyClientChannel.setCode("clientId:"+id);
                BootNettyClientChannelCache.save("clientId:"+id, bootNettyClientChannel);
                log.info("netty client start success={}",id);
                /**
                 * 等待连接端口关闭
                 */
                future.channel().closeFuture().sync();
            }
        } finally {
            /**
             * 退出，释放资源
             */
            group.shutdownGracefully().sync();
        }

    }
}
